// 泛型： 一个非常宽泛（广泛）的类型（核心：绝对不只是代表某一个类型）
// 场景： 声明一个函数类型 要求传入的参数类型和返回值类型一致

// 泛型的基本使用
function fn<T>(arg:T):T{
  return arg
}
// 指定泛型的类型
fn<string>('xxx')

// 如果不指定泛型的类型会进行 泛型类型推导
let res = fn(123)
let res1 = fn('xxx')


// 泛型的默认值
function test<T,U = any>(arg:T,abc?:U):T{
  return arg
}

const t1=test<number,string>(123,'xxx')
const str=test<string>('xxx')
test<boolean>(true)
// str.xxxx(); // 报错

// 如何理解泛型： 泛型是一个类型变量，它代表一个类型，这个类型有调用者决定

// 泛型的应用场景： 函数、类、接口、type声明一些类型工具
// 应用到接口的场景：后端API返回的数据格式基本确定{data:数据,code:状态码,msg:描述信息}, 但是data的数据类型不确定
interface IResultData<T> {
    code: number;
    msg: string;
    data: T;
}

type IUser = {
    username: string;
    age: number;
    sex: string;
}
// 商品列表接口
type IGoods = {
    id: number;
    name: string;
    price: number;
    desc: string;
}
// Array<IUser> ===> IUser[]
type UserListAPIType = IResultData<Array<IUser>>
type GoodsListAPIType = IResultData<IGoods[]>

// 使用泛型声明一些类型工具
type Pick<T,K extends keyof T> = {
    [P in K]:T[P]
}


// const promise:Promise<string> = new Promise((resolve,reject)=>{
//     setTimeout(()=>{
//         resolve('xxxx')
//     },1000)
// })

const promise = new Promise<{name:string,age:number}>((resolve,reject)=>{
    setTimeout(()=>{
        // resolve('xxxx')
        resolve({
            name:'张三',
            age:18
        })
    },1000)
})
// 获取Promise对象中的结果：
promise.then(res=>{
    console.log(res)
    // res.toUpperCase() // 报错
    // res.toFixed(2) // 报错
    res.age
})


async function getData(){
    const data=await promise;
    console.log(data);
}
getData()


// 泛型约束

function getLength<T extends {length:number}>(arg:T):number{
    return arg.length
}

getLength('xxxx')
getLength([]) // 报错


function getValue<T,K extends keyof T>(obj:T,key:K){
    return obj[key]
}

getValue({name:'张三',age:18},'age')


interface IUsers {
    name:string;
    age:number;
}

type IUserKeys = keyof IUsers // 获取一个类型中所有的key 'name' | 'age'

let key:IUserKeys = 'age'






export {}